package com.kang.c0c.util;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 类Log定义了整个编译器阶段的所有错误报告方法
 *
 * @author kang
 *
 * Feb 7, 2009
 */
public class Log implements LayoutCharacters{
	private static final Context.Key logKey = new Context.Key();
	
	public static Log instance(Context context){
		Log log = (Log)context.get(logKey);
		if(log == null){
			log = new Log(context);
		}
		
		return log;
	}
	
	protected Log(Context context){
		this(context,"src/com/kang/c0c/out//error.txt");
	}
	
	protected Log(Context context,String outFile){
		context.put(logKey, this);
		nerrors = 0;
		nwarnings = 0;
		buf = context.buf.toCharArray();
		
		if(outFile == null)
			out = new PrintWriter(System.err);
		else{
			out = null;
		
			try{
				File file = new File(outFile);
				
				if(file.exists() && !file.isDirectory()){
					out = new PrintWriter(file);
				}else if(! file.exists()){
					if(!file.createNewFile())
						System.err.println("Cann't create the new file " + file.getAbsolutePath());
					else
						out = new PrintWriter(file);
				}else{
					System.err.println("The output file is a directory!");
				}
			}catch(IOException ex){
				ex.printStackTrace();
			}
		}
		
		out.println("Error and Warning Log>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		out.println();
	}
	
	private int nerrors;
	private int nwarnings;
	private char[] buf;
	private PrintWriter out;
	
	private void printLine(int pos){
		int line = Position.getLine(pos);
		int col = Position.getColumn(pos);
		int lastLine = 1;
		int bp = 0;
		
		while(lastLine < line){
			switch(buf[bp]){
			case LF:
				bp++;
				lastLine ++;
				break;
			case CR:
				lastLine ++;
				bp++;
				if((bp < buf.length-1)&&(buf[bp] == LF))
					bp++;
				break;
			default:
				bp++;
				break;
			}
		}
		
		String str = "";
		while((bp<buf.length)
				&&(buf[bp]!=LF)
				&&(buf[bp]!=CR))
			str += buf[bp++];
		
		if((bp<buf.length)
				&&(buf[bp]==LF))
				str += buf[bp];
		out.println(str);	
		
		String ptr = "";
        for (int i = 0; i < col - 1; i++)
            ptr += ' ';
        ptr += '^';
        out.println(ptr);
	}
	
	public void error(int pos,String msg){
		nerrors ++;
		out.println("ERROR " + nerrors 
				+ " :-----------------------------------------------------------------------------");
		out.println("An error occuring at line "
				+ Position.getLine(pos) + " : " + msg);
		if(pos > 0)
			printLine(pos);
	}
	
	public void warn(int pos,String msg){
		nwarnings ++;
		out.println("WARNING " + nwarnings 
				+ " :-----------------------------------------------------------------------------");
		out.println("A warning for you at line "
				+ Position.getLine(pos) + " : " + msg);
		printLine(pos);
	}
	
	public void tips(String msg){
		out.println("Tips:" + msg);
	}

	public void analyzeReport(){
		out.println("---------------------------- " 
				+ this.nerrors + " Error(s) , " 
				+ this.nwarnings + " Warning(s)------------------------------------");
		out.close();
	}

	public int getNerrors() {
		return nerrors;
	}
}
